TDD coding kata - bulls and cows

  • Leetcode url

    https://leetcode.com/problems/bulls-and-cows/description/

  • Test Code

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    import (
    "testing"
    "github.com/stretchr/testify/assert"
    )

    func TestGuessAllCorrect(t *testing.T) {
    t.Run("guess4BullsAndNoCows", func(t *testing.T) {
    ret := getHint("1111", "1111")
    assert.Equal(t, "4A0B", ret, "guess4BullsAndNoCows failed")
    })

    t.Run("guessNoBullsAndCows", func(t *testing.T) {
    ret := getHint("1111", "2222")
    assert.Equal(t, "0A0B", ret, "guessNoBullsAndCows failed")
    })

    t.Run("guessOneBullAndNoCow", func(t *testing.T) {
    ret := getHint("1111", "1222")
    assert.Equal(t, "1A0B", ret, "guessOneBullAndNoCow failed")
    })

    t.Run("guessOneBullAndOneCow", func(t *testing.T) {
    ret := getHint("1112", "1323")
    assert.Equal(t, "1A1B", ret, "guessOneBullAndOneCow failed")
    })

    t.Run("guessOneBullAndOneCowWithDuplicateGuessNumber", func(t *testing.T) {
    ret := getHint("1112", "1223")
    assert.Equal(t, "1A1B", ret, "guessOneBullAndOneCowWithDuplicateGuessNumber failed")
    })

    t.Run("guessNoBullAndOneCowWithDuplicateGuessNumber", func(t *testing.T) {
    ret := getHint("1234", "0111")
    assert.Equal(t, "0A1B", ret, "guessNoBullAndOneCowWithDuplicateGuessNumber failed")
    })

    t.Run("guessNoBullAndFourCowWithDuplicateDigital", func(t *testing.T) {
    ret := getHint("1122", "2211")
    assert.Equal(t, "0A4B", ret, "guessNoBullAndFourCowWithDuplicateDigital failed")
    })

    t.Run("guessNoBullAndOneCowWithDuplicatePosition", func(t *testing.T) {
    ret := getHint("1122", "0001")
    assert.Equal(t, "0A1B", ret, "guessNoBullAndOneCowWithDuplicatePosition failed")
    })
    }
  • 实现代码

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    import "fmt"

    func getHint(secret, guess string) string {
    A := 0
    B := 0

    guessBytes := []byte(guess)
    secretBytes := []byte(secret)
    guessedByteMap := make(map[int]int)
    secretByteMap := make(map[int]int)

    for guestIndex, guestValue := range guessBytes {
    if guestValue == secretBytes[guestIndex] {
    setGuessAndSecretIndexPair(guessedByteMap, secretByteMap, guestIndex, guestIndex)
    A = increaseBullNumber(A)
    }
    }

    for guestIndex, guestValue := range guessBytes {
    for secretIndex, secretValue := range secretBytes {
    if guestIndex != secretIndex && guestValue == secretValue &&
    checkSecretAndGuessIndexUsed(guessedByteMap, secretByteMap, guestIndex, secretIndex) {
    B = increaseCowNumber(B)
    setGuessAndSecretIndexPair(guessedByteMap, secretByteMap, guestIndex, secretIndex)

    }
    }
    }

    return fmt.Sprintf("%dA%dB", A, B)
    }

    func increaseBullNumber(a int) int {
    return a + 1
    }

    func increaseCowNumber(b int) int {
    return b + 1
    }

    func setGuessAndSecretIndexPair(guessedByteMap map[int]int, secretByteMap map[int]int, guestIndex, secretIndex int) {
    guessedByteMap[guestIndex] = 1
    secretByteMap[secretIndex] = 1
    }

    func checkSecretAndGuessIndexUsed(guessedByteMap, secretByteMap map[int]int, guestIndex, secretIndex int) bool {
    return secretByteMap[secretIndex] == 0 && guessedByteMap[guestIndex] == 0
    }

    思路:遍历guess字符串两边,第一遍遍历产生bull个数,第二遍产生cows个数。需要两个map记录guess和secret被使用过的字符下标,避免重复计算